=begin pod

=TITLE class RatStr

=SUBTITLE Dual Value Rational number and String

    class RatStr is Rat is Str {}

The dual value types (often referred to as L<allomorphs|/language/glossary#Allomorph>)
allow for the representation of a value as both a string and a numeric type, typically
they will be created for you when the context is "stringy" but they can be determined
to be numbers, such as in some L<quoting constructs|/language/quoting>:

    my $f = <42.1>; say $f.^name; # OUTPUT: «RatStr␤»

As a subclass of both L«C<Rat>|/type/Rat» and L«C<Str>|/type/Str», a C<RatStr>
will be accepted where either is expected. However, C<RatStr> does not share
object identity with C<Rat>- or C<Str>-only variants:

    my $rat-str = <42.1>;
    my Rat $rat = $rat-str; # OK!
    my Str $str = $rat-str; # OK!
    say 42.1 ∈ <42.1  55  1>; # False; ∈ operator cares about object identity

=head1 Methods

=head2 method new

    method new(Rat $i, Str $s)

The constructor requires both the C<Rat> and the C<Str> value, when constructing one
directly the values can be whatever is required:

    my $f = RatStr.new(42.1, "forty two and a bit");
    say +$f; # OUTPUT: «42.1␤»
    say ~$f; # OUTPUT: «"forty two and a bit"␤»

=head2 method Bool

Defined as:

    multi method Bool(RatStr:D: --> Bool:D)

I<This method may be provided by the parent classes and not implemented in RatStr directly>.

Returns C<False> if the L<numerator> of the numeric portion is C<0>, otherwise returns C<True>.
This applies for C«< 0/0 >» zero-denominator L<RatStr> as well, despite C«?< 0/0 >.Num» being
C<True>. String portion is not considered.

=head2 method Capture

Defined as:

    method Capture(RatStr:D --> Capture:D)

Equivalent to L«C<Mu.Capture>|/type/Mu#method_Capture».

=head2 method Numeric

Defined as:

    multi method Numeric(RatStr:D: --> Rat:D)
    multi method Numeric(RatStr:U: --> Rat:D)

The C<:D> variant returns the numeric portion of the invocant. The C<:U> variant issues
a warning about using an uninitialized value in numeric context and then returns value C<0.0>.

=head2 method Rat

    method Rat

Returns the C<Rat> value of the C<RatStr>.

=head2 method Real

Defined as:

    multi method Real(Real:D: --> Rat:D)
    multi method Real(Real:U: --> Rat:D)

The C<:D> variant returns the numeric portion of the invocant. The C<:U> variant issues
a warning about using an uninitialized value in numeric context and then returns value C<0.0>.

=head2 method Str

Returns the string value of the C<RatStr>.

=head2 method ACCEPTS

Defined as:

    multi method ACCEPTS(RatStr:D: Any:D $value)

If C<$value> is L<Numeric> (including another
L<allomorph|/language/glossary#index-entry-Allomorph>), checks if invocant's
L<Numeric> part L<ACCEPTS|/type/Numeric#method_ACCEPTS> the C<$value>. If
C<$value> is L<Str>, checks if invocant's L<Str> part
L<ACCEPTS|/type/Str#method_ACCEPTS> the C<$value>. If value is anything else,
checks if both L<Numeric> and L<Str> parts C<ACCEPTS> the C<$value>.

    say <5.0> ~~ "5"; # OUTPUT: «False␤»
    say <5.0> ~~  5 ; # OUTPUT: «True␤»
    say <5.0> ~~ <5>; # OUTPUT: «True␤»

=head1 Operators

=head2 infix cmp

    multi sub infix:<cmp>(RatStr:D $a, RatStr:D $b)

Compare two C<RatStr> objects.  The comparison is done on the C<Rat> value first and
then on the C<Str> value. If you want to compare in a different order then you would
coerce to the C<Rat> or C<Str> values first:

    my $f = RatStr.new(42.1, "smaller");
    my $g = RatStr.new(43.1, "larger");
    say $f cmp $g;          # OUTPUT: «Less␤»
    say $f.Str cmp $g.Str;  # OUTPUT: «More␤»

=end pod

# vim: expandtab softtabstop=4 shiftwidth=4 ft=perl6
